﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions;

namespace FileSearcher
{
    public partial class MainForm : Form
    {
        BackgroundWorker bg = new BackgroundWorker();
        List<SearchResult> result = new List<SearchResult>();
        int count = 0;
        string curPath;
        string curKeyword;
        string curEncoding;
        bool curSubDir;
        bool curRegex;

        public MainForm()
        {
            InitializeComponent();
            comboBoxEncoding.SelectedIndex = 0;
            labelState.Text = "";
            bg.DoWork += this.SearchThread;
            bg.RunWorkerCompleted += this.PostSearch;
            bg.WorkerReportsProgress = true;
        }

        private void buttonSearchPath_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog dia = new FolderBrowserDialog();
            if (dia.ShowDialog() == DialogResult.OK)
            {
                textBoxSearchPath.Text = dia.SelectedPath;
            }
        }

        private void buttonSearch_Click(object sender, EventArgs e)
        {
            if (textBoxKeyword.Text.Trim() == "")
            {
                MessageBox.Show("搜索关键字不得为空！");
                return;
            }
            PreSearch();
            bg.RunWorkerAsync();
        }

        private void SearchThread(object sender, DoWorkEventArgs e)
        {
            SearchOn(curPath, curKeyword, curSubDir);
        }

        private void PreSearch()
        {
            labelState.Text = "";
            count = 0;
            result.Clear();
            dataGridViewResult.Rows.Clear();
            curPath = textBoxSearchPath.Text;
            curKeyword = textBoxKeyword.Text.Trim();
            curSubDir = checkBoxSubDir.Checked;
            curEncoding = comboBoxEncoding.Text;
            curRegex = checkBoxRegex.Checked;
            buttonSearch.Enabled = false;
        }

        private void PostSearch(object sender, RunWorkerCompletedEventArgs e)
        {
            labelState.Text = "搜索结束";
            UpdateUi();
            buttonSearch.Enabled = true;
        }

        private string[] Filter(string[] files)
        {
            List<string> res = new List<string>();
            Regex reg = new Regex(@"(\.(java)|(xml)|(cs)|(txt)|(css)|(jsp))$", RegexOptions.IgnoreCase);
            foreach (string file in files)
            {
                Match match = reg.Match(file);
                if (match.Success)
                    res.Add(file);
            }
            return res.ToArray();
        }

        private void SearchOn(string path, string keyword, bool subDir)
        {
            string[] files = Directory.GetFiles(path);
            if(curRegex)
                files = Filter(files);
            string[] dirs = Directory.GetDirectories(path);
            foreach (string file in files)
            {
                string content = null;
                try
                {
                    content = File.ReadAllText(file, Encoding.GetEncoding(curEncoding));
                }
                catch (IOException e)
                {
                    if (e.Message.Contains("being used by another process"))
                        continue;
                    else
                    {
                        MessageBox.Show(e.Message + "\n" + e.StackTrace);
                    }
                }
                string[] keywords = keyword.Split(new string[]{"@and"},StringSplitOptions.RemoveEmptyEntries);
                bool success = true;
                foreach (string sub in keywords)
                {
                    if (!content.Contains(sub.Trim()))
                    {
                        success = false;
                        break;
                    }
                }
                if (success)
                {
                    result.Add(new SearchResult(++count, file, null));
                }
            }
            if (subDir)
            {
                foreach (string dir in dirs)
                {
                    SearchOn(dir, keyword, subDir);
                }
            }
        }

        private void UpdateUi(SearchResult res)
        {
            dataGridViewResult.Rows.Add(res.GetAllAttributes());
        }

        private void UpdateUi()
        {
            foreach (SearchResult res in result)
            {
                UpdateUi(res);
            }
        }

        private void OnKeyUp(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Enter:
                    this.buttonSearch.PerformClick();
                    break;
            }
        }
    }
}
